package com.meridian.commerce.web;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.ui.Model;
import org.springframework.util.ClassUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.meridian.commerce.service.EntityCrudService;

@SessionAttributes({"parentEntityId","entityId"})

public abstract class AbstractCrudController<E> {

	private static final String CREATE_URI 	= "/create";
	private static final String UPDATE_URI 	= "/update";
	private static final String SHOW_URI 	= "/show";
	private static final String LIST_URI 	= "/list";

	@Autowired
	protected EntityCrudService<E> entityCrudService;
	
	protected static final String REDIRECT 				= "redirect:/";

	protected static final String PARENT_ENTITY_ID 		= "parentEntityId";
	protected static final String ENTITY_ID 			= "entityId";
	
	
	
	protected final String CONTROLLER_NAME    	= ClassUtils.getShortName(getEntityClass()).toLowerCase();
	
	protected final String ENTITY 				= ClassUtils.getShortNameAsProperty(getEntityClass());
	protected final String ENTITY_LIST 			= ENTITY + "List";
	
	protected final String LIST_VIEW 			= CONTROLLER_NAME + LIST_URI;
	protected final String SHOW_VIEW 			= CONTROLLER_NAME + SHOW_URI;
	protected final String UPDATE_VIEW 			= CONTROLLER_NAME + UPDATE_URI;
	protected final String CREATE_VIEW 			= CONTROLLER_NAME + CREATE_URI;
	
	public  AbstractCrudController() {
		SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(this.getClass(), SessionAttributes.class);
		sessionAttributes.value()[1]=ENTITY;
	}
	@RequestMapping(method = RequestMethod.GET)
	public String list( Model uiModel) {
		uiModel.addAttribute(ENTITY_LIST,entityCrudService.list());
		return LIST_VIEW;
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public String create(Model uiModel,WebRequest webRequest) {
		System.out.println("Entity: " + ENTITY);
		//webRequest.setAttribute(ENTITY,entityCrudService.newInstance(),WebRequest.SCOPE_SESSION);
		uiModel.addAttribute(ENTITY,entityCrudService.newInstance());
		return CREATE_VIEW ;
				
	}

	@RequestMapping(method = RequestMethod.POST)
	public String save(@Valid E entity, BindingResult bindingResult,  Model uiModel, WebRequest webRequest) {
		if (bindingResult.hasErrors()) {
			webRequest.setAttribute(ENTITY,entity,WebRequest.SCOPE_SESSION);
			return CREATE_VIEW;
		}
		entityCrudService.create(entity);
		return REDIRECT + LIST_VIEW ;
	}
		
	// TODO remove userAccountAddressId from url
	@RequestMapping(method = RequestMethod.GET)
	public String update(@RequestParam("entityId") Long entityId, Model uiModel) {
		uiModel.addAttribute(ENTITY, entityCrudService.findByPK(entityId));
		return UPDATE_VIEW;
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public String merge(@Valid E entity, BindingResult bindingResult, WebRequest webRequest) {
		if (bindingResult.hasErrors()) {
			webRequest.setAttribute(ENTITY,entity,WebRequest.SCOPE_SESSION);
			return UPDATE_VIEW;
		}
		entityCrudService.update(entity);
		return REDIRECT + LIST_VIEW;
	}


	// TODO remove userAccountAddressId from url
	@RequestMapping(method = RequestMethod.GET)
	public String delete(@PathVariable("entityId") Long entityId, Model uiModel, HttpServletRequest httpServletRequest) {
		entityCrudService.delete(entityId);
		uiModel.asMap().clear();
		return REDIRECT + LIST_VIEW;
	}

//	// TODO remove userAccountAddressId from url
//	@RequestMapping(value = "/{entityId}", method = RequestMethod.GET)
//	public String show() {
//		return SHOW_VIEW;
//	}
	
	
	
	String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
		String enc = httpServletRequest.getCharacterEncoding();
		if (enc == null) {
			enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
		}
		try {
			pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
		}
		catch (UnsupportedEncodingException uee) {}
		return pathSegment;
	}
	
	
	
//	@ModelAttribute(BINDED_OBJECT)
//    public E setupModel(@ModelAttribute(ENTITY_ID) Long entityId) {
//        if(entityId== null) {
//            return entityCrudService.newInstance();
//        } else {
//            return (E) entityCrudService.findByPK(entityId); 
//        }
//        
//    }	
	@SuppressWarnings("unchecked")
    protected Class<E> getEntityClass()
    {
        return (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
}
